----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    03:05:01 04/22/2011 
-- Design Name: 
-- Module Name:    Datapath - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library work;
use work.Definitions.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Datapath is

  Port (   clk_i : in  STD_LOGIC;	
			  clr_i : in STD_LOGIC;
			  flags_in_dp : in STD_LOGIC_VECTOR (1 downto 0);
			  instruction : in STD_LOGIC_VECTOR (17 downto 0);
			  data_word_i : in data_word_type;
			  port_word_i : in port_word_type;
			  
			  --flags
			  is_ret_state 	   : in  STD_LOGIC;
		     reg_flag_enable 	: in STD_LOGIC;
			  --alu
			  is_sh_rot 		: in  STD_LOGIC;
			  --mult 2_1 data
			  is_load 	: in  STD_LOGIC;
			  --mult immediate
			  is_immediate : in  STD_LOGIC;
			  --mult w
			  is_in 	: STD_LOGIC;
           --is_load 	: in  STD_LOGIC;
			  --reg file
			  reg_file_we	: in  std_logic;
			  --reg acc
			  --reg data
           enable_data 	 : in  STD_LOGIC;
			  --mult_operation
			  is_alu : in STD_LOGIC;
			  
			  dp_flags_out: out STD_LOGIC_VECTOR (1 DOWNTO 0);
			  data_port_word_o1 : out data_word_type;
			  data_port_word_o2 : out data_word_type
			  );

end Datapath;

architecture Behavioral of Datapath is

component ALU 
     Port ( inp_A 			: in  STD_LOGIC_VECTOR (7 downto 0);
			inp_B 			: in  STD_LOGIC_VECTOR (7 downto 0);
			op_type 		: in  STD_LOGIC_VECTOR (2 downto 0);
			sh_rot_count 	: in  STD_LOGIC_VECTOR (2 downto 0);
			is_sh_rot 		: in  STD_LOGIC;
			cry_in 			: in  STD_LOGIC;
			alu_out 		: out  STD_LOGIC_VECTOR (7 downto 0);
			flags_out 		: out  STD_LOGIC_VECTOR (1 downto 0));
end component ALU;

component Mult_Data_Port
	 Port ( dataw : in  data_word_type;
           portw : in  port_word_type;
           is_load : in  STD_LOGIC;
		     output : out  std_logic_vector (7 downto 0));
end component Mult_Data_Port;

component Flags
    Port ( clk_i        		: in  STD_LOGIC;
           clr_i        		: in  STD_LOGIC;
           flags_in     		: in  STD_LOGIC_VECTOR (1 downto 0);
			  flags_alu 			: in  STD_LOGIC_VECTOR (1 downto 0);
           is_ret_state 		: in  STD_LOGIC;
			  reg_flag_enable 	: in STD_LOGIC;
           flags_out 			: out  STD_LOGIC_VECTOR (1 downto 0));
end component Flags;

component Mult_W
  Port (   dataw 		: in  data_word_type;
           accw 		: in  data_word_type;
			  is_in 		: in STD_LOGIC;
           is_load 	: in  STD_LOGIC;
           outputw 	: out  std_logic_vector (7 downto 0));
end component Mult_W;

component Mult_Operation
    Port ( a 			: in  ext3;
           b 			: in  ext3;
           control 	: in  STD_LOGIC;
           salida 	: out  ext3);
end component Mult_Operation;

component Mult_Immediate
    Port ( in1 : in  data_addr_type;
           in2 : in  data_addr_type;
           hola : in  STD_LOGIC;
           output : out  data_addr_type);
end component Mult_Immediate;

component RegisterFile
	Port (  a1 			: in  std_logic_vector(2 DOWNTO 0);
           a2 			: in  std_logic_vector(2 DOWNTO 0);
           a3 			: in  std_logic_vector(2 DOWNTO 0);
           w_in 		: in  std_logic_vector (7 downto 0);
		     clk			: in std_logic;
		     reg_file_we	: in  std_logic;
           r1 			: out  data_word_type;
           r2 			: out  data_word_type);
end component RegisterFile;

component Register_Data_Acc
	Port ( data_in	 	 : in  data_word_type;
           clk_i 		 : in  STD_LOGIC;
           clr_i		 : in  STD_LOGIC;
           enable_data 	 : in  STD_LOGIC;
           data_out 	 : out  data_word_type);
end component Register_Data_Acc;

signal data_in : data_word_type;
signal data_out : data_word_type;
signal output_w : data_word_type;
signal r1_output : data_word_type;
signal r2_output : data_word_type;
signal output_i : data_word_type;
signal optype :  STD_LOGIC_VECTOR (2 downto 0);
signal alu_out : data_word_type;
signal flags_out_alu : STD_LOGIC_VECTOR (1 downto 0);
--signal flags_alu_in : STD_LOGIC_VECTOR (1 downto 0);
signal acc_out : data_word_type;
signal is_alu_reg : STD_LOGIC;
signal is_alu_immediate : STD_LOGIC;


alias rs1: STD_LOGIC_VECTOR(2 downto 0) is instruction(10 downto 8);
alias rs2: STD_LOGIC_VECTOR(2 downto 0) is instruction(7 downto 5);
alias rd: STD_LOGIC_VECTOR(2 downto 0) is instruction(13 downto 11);
alias sh_rot_count: STD_LOGIC_VECTOR (2 downto 0) is instruction(7 downto 5);
alias cry_in : STD_LOGIC is dp_flags_out(0);

alias most_optype : STD_LOGIC_VECTOR(2 downto 0) is instruction(16 downto 14);
alias less_optype : STD_LOGIC_VECTOR(2 downto 0) is instruction(2 downto 0);

alias immediate_data: STD_LOGIC_VECTOR(7 downto 0) is instruction(7 downto 0);

begin

mult_a:Mult_Data_Port 
port map (data_word_i, port_word_i, is_load, data_in);

reg_data:Register_Data_Acc 
port map(data_in, clk_i, clr_i, enable_data, data_out);

mult_b:Mult_W
port map (data_out, acc_out, is_in, is_load, output_w);

register_dp:RegisterFile
port map (rs1, rs2, rd, output_w, clk_i, reg_file_we, r1_output, r2_output);

is_alu_immediate <= is_alu AND is_immediate;-- interrupcion para decidir si es reg o immediate

mult_c:Mult_Data_Port
port map (immediate_data, r2_output, is_alu_immediate, output_i);

is_alu_reg <= is_alu AND is_immediate;-- interrupcion para decidir si es reg o immediate
mult_optype:Mult_Operation
port map(most_optype, less_optype, is_alu_reg, optype);

alu1:ALU
port map (r1_output, output_i, optype, sh_rot_count, is_sh_rot, cry_in, alu_out, flags_out_alu);

flags1:Flags
port map (clk_i, clr_i, flags_in_dp, flags_out_alu, is_ret_state, reg_flag_enable, dp_flags_out);

reg_acc: Register_Data_Acc
port map (alu_out, clk_i, clr_i, enable_data, acc_out);

data_port_word_o1 <= acc_out;
data_port_word_o2 <= r2_output;


end Behavioral;

